package com.eobard.adapter;

import cn.hutool.core.util.StrUtil;
import com.eobard.utils.FileUtils;
import com.eobard.utils.ObfuscatorUtils;
import com.github.javaparser.ParserConfiguration;
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * @Author: Eobard Gu
 * @Date: 2025-08-04
 * @Description: 通过加载源码和扩展源码建立静态类型解析器, 让JavaParser在不运行代码的情况下也能“知道”每个方法、类、变量到底是哪来的。
 * 如果源码方法中使用了其它库的方法,如果不加载到AST语法树中,JavaParser不能找到对应类和方法的定义
 */
@Slf4j
public abstract class BaseVisitorAdapter<A> extends VoidVisitorAdapter<A> {

    @Value("${obfuscate.enable.typeSolver.logging:false}")
    private boolean print;

    @Value("${obfuscate.static.method.path:temp/methods/TempStaticMethods.java}")
    private String staticMethodPath;

    private static boolean PRINT;
    protected static String staticMethodsFilePath;

    //添加代码引用关联
    public static void initSolver(String sourceRoot, String sourceExt) {
        CombinedTypeSolver solver = new CombinedTypeSolver(
                new JavaParserTypeSolver(sourceRoot), new ReflectionTypeSolver()
        );
        //源码包
        File extDir = null;
        if (StrUtil.isNotEmpty(sourceExt)) {
            try {
                extDir = FileUtils.copyClasspathSourceToTempDir(sourceExt);
                log.info("copy source file to temp directory:{}", extDir.getPath());
                JavaParserTypeSolver typeSolver = new JavaParserTypeSolver(extDir);
                solver.add(typeSolver);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        if (PRINT) {
            log.info("✔✔✔ CombinedTypeSolver 可识别的类如下：");
            List<String> classNames = ObfuscatorUtils.scanJavaClassNames(sourceRoot);
            classNames.addAll(ObfuscatorUtils.scanJavaClassNames(extDir.toString()));
            classNames.forEach(className -> {
                try {
                    solver.solveType(className);
                    log.info("   - ✅ " + className);
                } catch (Exception e) {
                    log.info("   - ❌ " + className + " 无法解析,错误信息:" + e.getMessage());
                }
            });
        }
        StaticJavaParser.getParserConfiguration().setSymbolResolver(new JavaSymbolSolver(solver));
    }


    @PostConstruct
    public void init() {
        PRINT = print;
        staticMethodsFilePath=staticMethodPath;
        //设置java的版本为17
        StaticJavaParser.getParserConfiguration().setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_17);
    }
}
